package com.hskn.hss.module.alarmcar.controller;


import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hskn.hss.constant.CommonConstant;
import com.hskn.hss.core.annotation.SysLog;
import com.hskn.hss.core.controller.BaseController;
import com.hskn.hss.core.domain.BaseEntity;
import com.hskn.hss.core.enums.BusinessType;
import com.hskn.hss.core.utils.poi.ExcelUtil;
import com.hskn.hss.entity.AbnormalResult;
import com.hskn.hss.entity.AjaxResult;
import com.hskn.hss.exception.HssException;
import com.hskn.hss.module.alarmcar.entity.AlarmCar;
import com.hskn.hss.module.alarmcar.mapper.AlarmCarMapper;
import com.hskn.hss.module.alarmcar.service.IAlarmCarService;
import com.hskn.hss.module.alarmcar.vo.AlarmCarChartsExcelVO;
import com.hskn.hss.module.alarmcar.vo.AlarmCarTableDetailExcelVO;
import com.hskn.hss.module.alarmcar.vo.AlarmCarVO;
import com.hskn.hss.module.alarmperson.entity.AlarmPerson;
import com.hskn.hss.module.alarmperson.mapper.AlarmPersonMapper;
import com.hskn.hss.module.carTrack.entity.CarTrack;
import com.hskn.hss.module.carTrack.mapper.CarTrackMapper;
import com.hskn.hss.module.common.to.OilNumTO;
import com.hskn.hss.module.depart.entity.SysDepart;
import com.hskn.hss.module.depart.service.impl.SysDepartServiceImpl;
import com.hskn.hss.module.employeeTrack.entity.EmployeeTrack;
import com.hskn.hss.module.employeeTrack.mapper.EmployeeTrackMapper;
import com.hskn.hss.module.kfkdeal.entity.car.KfkHandleParam;
import com.hskn.hss.module.kfkdeal.service.impl.KfkHandleServiceImpl;
import com.hskn.hss.module.tlcar.entity.TlCar;
import com.hskn.hss.module.tlcar.mapper.TlCarMapper;
import com.hskn.hss.module.tlcar.service.ITlCarService;
import com.hskn.hss.module.tlcartype.entity.TlCarType;
import com.hskn.hss.module.tlcartype.service.ITlCarTypeService;
import com.hskn.hss.module.tlemployee.entity.TlEmployee;
import com.hskn.hss.module.tlemployee.mapper.TlEmployeeMapper;
import com.hskn.hss.module.tlequip.entity.TlEquip;
import com.hskn.hss.module.tlequip.mapper.TlEquipMapper;
import com.hskn.hss.module.tlequip.service.impl.TlEquipServiceImpl;
import com.hskn.hss.module.tlthreshold.entity.TlThreshold;
import com.hskn.hss.module.tlthreshold.mapper.TlThresholdMapper;
import com.hskn.hss.module.tlthreshold.service.ITlThresholdService;
import com.hskn.hss.utils.*;
import com.hskn.hss.utils.PerformanceMonitor.PerformanceMonitor;
import com.hskn.hss.utils.redis.RedisUtil;
import com.hskn.hss.utils.redis.key.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author hskn
 * @since 2021-05-21
 */
@Api(tags = {"-tl_alarm_car"}, description = "车辆报警")
@Slf4j
@RestController
@RequestMapping("/hss/alarmcar")
public class AlarmCarController extends BaseController {

    @Autowired
    private IAlarmCarService alarmCarService;
    @Resource
    private AlarmCarMapper alarmCarMapper;
    @Resource
    private KfkHandleServiceImpl kfkHandleServiceImpl;
    @Autowired
    private ITlCarService tlCarService;
    @Autowired
    private ITlThresholdService tlThresholdService;
    @Autowired
    private LocationUtils locationUtil;
    @Autowired
    private SysDepartServiceImpl departService;
    @Resource
    private TlCarMapper tlCarMapper;
    @Resource
    private TlEquipServiceImpl tlEquipService;
    @Autowired
    private ITlCarTypeService tlCarTypeService;
    @Resource
    private CarTrackMapper carTrackMapper;
    @Resource
    private TlEmployeeMapper tlEmployeeMapper;
    @Resource
    AlarmPersonMapper alarmPersonMapper;
    @Resource
    TlThresholdMapper tlThresholdMapper;
    @Autowired
    AlarmUtils alarmUtils;
    @Resource
    private EmployeeTrackMapper employeeTrackMapper;
    @Autowired
    private SysDepartServiceImpl sysDepartService;

    @RequestMapping(value = "list", method = RequestMethod.POST)
    public AjaxResult<Object> list(HttpServletRequest request) {
        try {
            BaseEntity entity = new BaseEntity();
            JSONObject params = JSON.parseObject(Tools.getBody(request));
            JSONObject json = alarmCarService.mList(entity, params);
            return AjaxResult.success(json);
        } catch (HssException e) {
            return AjaxResult.fail(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("报错ERROR", e);
            return AjaxResult.fail("操作失败");
        }
    }

    @ApiOperation(value = "当天车辆异常接口", notes = "当天车辆异常")
    @RequestMapping(value = "abnormal", method = RequestMethod.POST)
    public AjaxResult<Object> abnormal(HttpServletRequest request) {
        try {
            BaseEntity entity = new BaseEntity();
            JSONObject params = JSON.parseObject(Tools.getBody(request));
            JSONObject json = alarmCarService.getAbnormal();
            return AjaxResult.success(json);
        } catch (HssException e) {
            return AjaxResult.fail(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("报错ERROR", e);
            return AjaxResult.fail("操作失败");
        }
    }

    @SysLog(businessType = BusinessType.UPDATE, tableName = "alarm_car", idKey = "alarmCarIds", bean = AlarmCar.class, beanMapper = AlarmCarMapper.class, names = "depName, carName")
    @ApiOperation(value = "批量处理接口", notes = "批量处理")
    @RequestMapping(value = "deal", method = RequestMethod.POST)
    public AjaxResult<Object> deal(HttpServletRequest request) {
        try {
            JSONObject params = JSON.parseObject(Tools.getBody(request));
            alarmCarService.deal(params);
            return AjaxResult.success("处理成功");
        } catch (HssException e) {
            return AjaxResult.fail(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("报错ERROR", e);
            return AjaxResult.fail("操作失败");
        }
    }


    /**
     * 报警统计
     * @param request
     * @return
     */
    @RequestMapping(value = "selectAlarmCarForCharts", method = RequestMethod.POST)
    public AjaxResult<Object> selectAlarmCarForCharts(HttpServletRequest request) {
        try {
            JSONObject params = JSON.parseObject(Tools.getBody(request));
            AlarmCar alarmCar=new AlarmCar();
            if(params!=null){
                alarmCar=JSONObject.parseObject(params.toJSONString(),AlarmCar.class);
            }
            return AjaxResult.success(alarmCarService.selectAlarmCarForCharts(alarmCar));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("报错ERROR", e);
            return AjaxResult.fail("操作失败");
        }
    }
    /**
     * 报警统计
     * @param request
     * @return
     */
    @RequestMapping(value = "selectAlarmCarForTable", method = RequestMethod.POST)
    public AjaxResult<Object> selectAlarmCarForTable(HttpServletRequest request) {
        try {
            JSONObject params = JSON.parseObject(Tools.getBody(request));
            AlarmCar alarmCar=new AlarmCar();
            if(params!=null&&params.containsKey("pageNum")&&params.containsKey("pageSize")){
                startPage(params.getInteger("pageNum"),params.getInteger("pageSize"));
            }else{
                return AjaxResult.fail("pageNum，pageSize不能为空");
            }
            if(params!=null){
                alarmCar=JSONObject.parseObject(params.toJSONString(),AlarmCar.class);
            }
            return AjaxResult.success(Tools.getDataTable(alarmCarService.selectAlarmCarForTable(alarmCar)));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("报错ERROR", e);
            return AjaxResult.fail("操作失败");
        }
    }

    @PostMapping("excelExport")
    public com.hskn.hss.core.domain.AjaxResult excelExport(HttpServletRequest request) {
        try {
            JSONObject params = JSON.parseObject(Tools.getBody(request));

            QueryWrapper<AlarmCar> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().orderByDesc(AlarmCar::getCreateTime);

            if (StringUtils.isNotEmpty(params.getString("ids"))){
                List<String> ids= Arrays.asList(params.getString("ids").split(","));
                if(StringUtils.isNotEmpty(ids) && !(ids.size() ==1 && StringUtils.isEmpty(String.valueOf(ids.get(0))))){
                    queryWrapper.lambda().in(AlarmCar::getAlarmCarId,ids);
                }
            }
            String alarmCarId = params.getString("alarmCarId");
            if (StringUtils.isNotEmpty(alarmCarId)) {
                queryWrapper.lambda().eq(AlarmCar::getAlarmCarId, alarmCarId);
            }
            String carId = params.getString("carId");
            if (StringUtils.isNotEmpty(carId)) {
                queryWrapper.lambda().eq(AlarmCar::getCarId, carId);
            }
            String alarmTypeId = params.getString("alarmTypeId");
            if (StringUtils.isNotEmpty(alarmTypeId)) {
                queryWrapper.lambda().eq(AlarmCar::getAlarmTypeId, alarmTypeId);
            }
            String alarmTypeName = params.getString("alarmTypeName");
            if (StringUtils.isNotEmpty(alarmTypeName)) {
                queryWrapper.lambda().like(AlarmCar::getAlarmTypeName, alarmTypeName);
            }
            String startDate = params.getString("startDate");
            String endDate = params.getString("endDate");
            if (StringUtils.isNotEmpty(startDate) && StringUtils.isNotEmpty(endDate)) {
                queryWrapper.lambda().between(AlarmCar::getAlarmTime, startDate + " 00:00:00", endDate + " 23:59:59");
            }
            List<AlarmCar> alarmCars = alarmCarMapper.selectList(queryWrapper);

            //工具类实例化
            ExcelUtil<AlarmCarVO> util = new ExcelUtil<>(AlarmCarVO.class);
            //数据载体转换
            List<AlarmCarVO> alarmCarVO=JSONObject.parseArray(JSONObject.toJSONString(alarmCars),AlarmCarVO.class);
            //导出
            return util.exportExcel(alarmCarVO,"车辆报警");

        } catch (Exception e) {
            e.printStackTrace();
            return com.hskn.hss.core.domain.AjaxResult.error();
        }

    }

    /**
     * 修复漏油超速数据
     * @param oilNumTO
     */
    @PostMapping("/updateAlarmCar")
    public void updateAlarmCar(@RequestBody @Validated OilNumTO oilNumTO) {
        PerformanceMonitor.begin("-----------------------修复漏油超速数据执行时间------------------~");
        //车辆轨迹queryWrapper
        QueryWrapper<CarTrack> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().orderByAsc(CarTrack::getTimestamp);
        queryWrapper.lambda().ge(CarTrack::getTimestamp, oilNumTO.getStartTime());
        queryWrapper.lambda().le(CarTrack::getTimestamp, oilNumTO.getEndTime());
        List<CarTrack> carTrackList = carTrackMapper.selectList(queryWrapper);
        Map<String, TlCar> carMap = tlCarService.getCarMap(new QueryWrapper<>());
        Map<String, SysDepart> departMap = departService.getDepartMap(new QueryWrapper<>());

        Map<String, List<CarTrack>> carTrackMap = carTrackList.stream().collect(Collectors.groupingBy(CarTrack::getCarId));
        carTrackMap.keySet().forEach(carId->{
            TlCar tlCar = carMap.get(carId);
            if (Objects.nonNull(tlCar)){
                if (StringUtils.isNotEmpty(tlCar.getDeptid())){
                    SysDepart sysDepart = departMap.get(tlCar.getDeptid());
                    if (Objects.nonNull(sysDepart) && StringUtils.isNotEmpty(sysDepart.getDepartName())){
                        tlCar.setCardeptname(sysDepart.getDepartName());
                    }
                }

                List<CarTrack> carTracks = carTrackMap.get(carId);

                if (Objects.nonNull(carTracks) && carTracks.size() > 0){
                        //按照设备上传定位时间正序排序
                        Collections.sort(carTracks, (o1, o2) -> {
                            Date d1 = o1.getTimestamp();
                            Date d2 = o2.getTimestamp();
                            return d1.compareTo(d2);
                        });
                }

                List<TlThreshold> tlThresholdList = tlThresholdService.getCarThresholdsFromRedis(carId);
                for (TlThreshold tlThreshold : tlThresholdList) {
                    for (int i = 0; i < carTracks.size(); i++) {
                        String today = DateUtil.formatDate(carTracks.get(i).getTimestamp());
                        //保存车辆报警表
                        KfkHandleParam kfkHandleParam = new KfkHandleParam();
                        kfkHandleParam.setCarId(carId);
                        kfkHandleParam.setLocationDate(carTracks.get(i).getTimestamp());
                        kfkHandleParam.setTlCar(tlCar);
                        kfkHandleParam.setSpeed(carTracks.get(i).getSpeed());
                        kfkHandleParam.setLon(carTracks.get(i).getLng());
                        kfkHandleParam.setLat(carTracks.get(i).getLat());
                        /** 保存地址 **/
                        String currentAddress = locationUtil.getAddress(carTracks.get(i).getLng(), carTracks.get(i).getLat());
                        if (StringUtils.isNotEmpty(currentAddress)){
                            kfkHandleParam.setCurrentAddress(currentAddress);
                        } else {
                            kfkHandleParam.setCurrentAddress("");
                        }
                        kfkHandleParam.setLocationDate(carTracks.get(i).getTimestamp());
                        kfkHandleParam.setCurrentSystemDate(carTracks.get(i).getTimestamp());

                        Integer twoPointTimeDiffer;
                        if (i > 1) {
                            twoPointTimeDiffer = StringUtils.calLastedTime(carTracks.get(i-1).getTimestamp(), carTracks.get(i).getTimestamp());
                        } else {
                            twoPointTimeDiffer = StringUtils.calLastedTime(StringUtils.getZeroHourToday(), carTracks.get(i).getTimestamp());
                        }

                        String sysname = tlThreshold.getSysname();
                        switch (sysname) {
                            case "超速":
                                if ("0".equals(tlThreshold.getStatus())) {
                                    break;
                                }
                                JSONObject speedThresholdDetail = JSONObject.parseObject(tlThreshold.getThreshold());

                                if (kfkHandleParam.getSpeed() >= Double.parseDouble(speedThresholdDetail.get("xs").toString())) {
                                    //某时间段最大速
                                    int maxSpeed = Objects.nonNull(RedisUtil.get(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class) : 0;
                                    if (kfkHandleParam.getSpeed() > maxSpeed) {
                                        RedisUtil.set(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, kfkHandleParam.getSpeed());
                                    }

                                    int carAlarmSpeedKeepTime = Objects.nonNull(RedisUtil.get(CarAlarmSpeedKeepTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarAlarmSpeedKeepTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class) + twoPointTimeDiffer : twoPointTimeDiffer;
                                    RedisUtil.set(CarAlarmSpeedTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, carAlarmSpeedKeepTime);

                                    //保存车辆报警表
                                    AbnormalResult abnormalResult = kfkHandleServiceImpl.saveAlarmCar(kfkHandleParam, tlThreshold, new Date(kfkHandleParam.getLocationDate().getTime() - 1000 * twoPointTimeDiffer));
                                } else if (kfkHandleParam.getSpeed() >= Double.parseDouble(speedThresholdDetail.get("m_xs").toString())) {
                                    //速度持续时间(分钟)
                                    JSONObject threshold1 = JSONObject.parseObject(tlThreshold.getThreshold());
                                    int duration = 60 * Integer.parseInt(threshold1.get("m_sj").toString());

                                    //超速模式一达到阈值持续保持时间
                                    int carAlarmSpeedKeepTime = Objects.nonNull(RedisUtil.get(CarAlarmSpeedKeepTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarAlarmSpeedKeepTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class) + twoPointTimeDiffer : twoPointTimeDiffer;
                                    RedisUtil.set(CarAlarmSpeedTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, carAlarmSpeedKeepTime);

                                    //超过阈值
                                    if (carAlarmSpeedKeepTime >= duration * 60) {
                                        //某时间段最大速
                                        int maxSpeed = Objects.nonNull(RedisUtil.get(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class) : 0;
                                        if (kfkHandleParam.getSpeed() > maxSpeed) {
                                            RedisUtil.set(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, kfkHandleParam.getSpeed());
                                        }

                                        String starttime = DateUtil.formatDateTime(new Date(kfkHandleParam.getLocationDate().getTime() - 1000 * duration * 60));
                                        //保存车辆报警表
                                        AbnormalResult abnormalResult = kfkHandleServiceImpl.saveAlarmCar(kfkHandleParam, tlThreshold, DateUtil.parseDateTime(starttime));
                                    }
                                } else {
                                    //超速持续保持时间
                                    RedisUtil.set(CarAlarmSpeedTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, 0);
                                    //某时间段最大速
                                    RedisUtil.set(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, 0);
                                }
                                break;
                            case "漏油":
                                // 油量为0时不处理
                                if (new BigDecimal(carTracks.get(i).getOilMass().toString()).compareTo(BigDecimal.ZERO) <= 0) {
                                    break;
                                }

                                //检测时间间隔
                                int timeinterval;//单位分钟
                                //阀值油耗限额
                                BigDecimal yhxe;
                                timeinterval = tlThreshold.getTimeinterval();
                                JSONObject threshold1 = JSONObject.parseObject(tlThreshold.getThreshold());
                                yhxe = new BigDecimal(threshold1.get("yhxe").toString());
                                Map consumptionPer = kfkHandleServiceImpl.getConsumptionPer(carId, StringUtils.DateFormat(new Date(carTracks.get(i).getTimestamp().getTime() - 1000 * 60 * timeinterval)), StringUtils.DateFormat(carTracks.get(i).getTimestamp()));
                                //获取检测时间间隔的总耗油
                                BigDecimal oilMassSum = new BigDecimal(String.valueOf(consumptionPer.get("oilMassSum")));

                                if (oilMassSum.compareTo(yhxe) > 0) {

                                    int carAlarmSpeedKeepTime = Objects.nonNull(RedisUtil.get(CarAlarmOilTimeKeyToday.token, carId + "_" + today, int.class)) ? RedisUtil.get(CarAlarmOilTimeKeyToday.token, carId + "_" + today, int.class) + 1000 * 60 * timeinterval : 1000 * 60 * timeinterval;
                                    RedisUtil.set(CarAlarmOilTimeKeyToday.token, carId + "_" + today, carAlarmSpeedKeepTime);

                                    AbnormalResult abnormalResult = kfkHandleServiceImpl.saveAlarmCar(kfkHandleParam, tlThreshold, new Date(carTracks.get(i).getTimestamp().getTime() - 1000 * 60 * timeinterval));

                                } else {
//                        //漏油持续时间
                                    RedisUtil.set(CarAlarmOilTimeKeyToday.token, carId + "_" + today, 0);
                                    //最大百公里油耗
                                    RedisUtil.set(CarAlarmAvgOilConsumptionKeyToday.token, carId + "_" + today, "0");
                                }
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
        });
        PerformanceMonitor.end();
    }

    /**
     * 修复离线数据
     * @param oilNumTO
     */
    @PostMapping("/updateAlarmCarLx")
    public void updateAlarmCarLx(@RequestBody @Validated OilNumTO oilNumTO) {

        PerformanceMonitor.begin("-----------------------修复离线报警数据执行时间------------------~");
        String today = DateUtil.formatDate(DateUtil.parseDate(oilNumTO.getStartTime()));

        Map<String, SysDepart> departMap = sysDepartService.getDepartMap(new QueryWrapper<>());

        //查询所有设备
        QueryWrapper<TlEquip> tlEquipQueryWrapper = new QueryWrapper<>();
        tlEquipQueryWrapper.lambda().eq(TlEquip::getStatus, "1");//启用
        tlEquipQueryWrapper.lambda().eq(TlEquip::getBindstatus, "1");//已绑定设备
        Map<String, TlEquip> tlEquipMap = tlEquipService.getTlEquipMapByBindobjidMap(new QueryWrapper<>());

        //查询所有绑设备的人员
        QueryWrapper<TlEmployee> tlEmployeeQueryWrapper = new QueryWrapper<>();
        tlEmployeeQueryWrapper.lambda().eq(TlEmployee::getStatus, "1");//在职
        List<TlEmployee> tlEmployeeList = tlEmployeeMapper.selectList(tlEmployeeQueryWrapper);

        String startTime = AttributeUtils.timeCompletion(today, 's');
        String endTime = AttributeUtils.timeCompletion(today, 'e');

        //查询所有报警参数
        QueryWrapper<TlThreshold> tlThresholdQueryWrapper = new QueryWrapper<>();
        tlThresholdQueryWrapper.lambda().eq(TlThreshold::getSysname, "离线");
        List<TlThreshold> tlThresholdList = tlThresholdMapper.selectList(tlThresholdQueryWrapper);
        Map<String, TlThreshold> thresholdMap = tlThresholdList.stream().collect(Collectors.groupingBy(TlThreshold::getItemid, Collectors.collectingAndThen(toList(), tlThresholds -> tlThresholds.get(0))));

        //查询所有人员记录
        QueryWrapper<EmployeeTrack> employeeTrackQueryWrapper = new QueryWrapper<>();
        employeeTrackQueryWrapper.lambda().ge(EmployeeTrack::getTimestamp,startTime);
        employeeTrackQueryWrapper.lambda().le(EmployeeTrack::getTimestamp,endTime);
        List<EmployeeTrack> employeeTracks = employeeTrackMapper.selectList(employeeTrackQueryWrapper);

        Map<String, List<EmployeeTrack>> employeeTrackMap = employeeTracks.stream().collect(Collectors.groupingBy(EmployeeTrack::getEmployeeId));

        log.info("===================人员离线报警开始===============");
        for (TlEmployee tlEmployee : tlEmployeeList) {
            TlEquip tlEquip = tlEquipMap.get(tlEmployee.getId());
            if (Objects.nonNull(tlEquip)) {
                String eqpnum = tlEquip.getEquipcode();
                String personId = "";
                int calctime = 0;
                Map thvalue = alarmUtils.getCompare(eqpnum, "离线");
                if (thvalue != null && thvalue.size() > 0) {
                    int cmpvalue = Integer.parseInt(String.valueOf(thvalue.get("lx"))) * 60;
                    String objid = String.valueOf(thvalue.get("objid"));
                    String thresholdid = String.valueOf(thvalue.get("thresholdid"));
                    String sysname = String.valueOf(thvalue.get("sysname"));

                    JSONObject param = new JSONObject();
                    param.put("id", objid);

                    personId = tlEmployee.getId();

                    List<EmployeeTrack> employeeTrackList = employeeTrackMap.get(personId);

                    Date alarmStartTime = DateUtil.parseDateTime(AttributeUtils.timeCompletion(today, 's'));
                    Date alarmTime = new Date(DateUtil.parseDateTime(AttributeUtils.timeCompletion(today, 's')).getTime() + 1000*60*30);
                    Date alarmEndTime = DateUtil.parseDateTime(AttributeUtils.timeCompletion(today, 'e'));

                    if (Objects.nonNull(employeeTrackList) && employeeTrackList.size() > 0){
                        //按照设备上传定位时间正序排序
                        Collections.sort(employeeTrackList, (o1, o2) -> {
                            Date d1 = o1.getTimestamp();
                            Date d2 = o2.getTimestamp();
                            return d1.compareTo(d2);
                        });

                        Boolean flag = true;
                        for (int i = 0; i < employeeTrackList.size(); i++) {

                            if (i == 0) {
                                calctime = StringUtils.calLastedTime(alarmStartTime,employeeTrackList.get(i).getTimestamp());
                            } else {
                                calctime = StringUtils.calLastedTime(employeeTrackList.get(i-1).getTimestamp(),employeeTrackList.get(i).getTimestamp());
                                alarmStartTime = employeeTrackList.get(i-1).getTimestamp();
                                alarmTime = new Date(alarmStartTime.getTime() + 1000*60*30);
                            }
                            alarmEndTime = employeeTrackList.get(i).getTimestamp();

                            TlThreshold tlThreshold = thresholdMap.get(personId);
                            if (Objects.nonNull(thresholdid) && StringUtils.isNotEmpty(tlThreshold.getStatus()) && CommonConstant.THRESHOLD_STATUS_YES.equals(tlThreshold.getStatus())) {
                                if (calctime >= cmpvalue) {
                                    AlarmPerson alarmPerson1 = RedisUtil.get(CarPersonTypeNameLastOneKeyToday.token, tlEmployee.getId() + "_" + "离线" + "_" + today, AlarmPerson.class);

                                    if (Objects.isNull(alarmPerson1)) {
                                        QueryWrapper<AlarmPerson> queryWrapper = new QueryWrapper<>();
                                        queryWrapper.lambda().eq(AlarmPerson::getPersonId, tlEmployee.getId());
                                        queryWrapper.lambda().eq(AlarmPerson::getAlarmTypeName, "离线");
                                        queryWrapper.lambda().between(AlarmPerson::getAlarmTime, startTime, endTime);
                                        queryWrapper.lambda().orderByDesc(AlarmPerson::getAlarmTime);
                                        queryWrapper.lambda().last(" LIMIT 1");
                                        alarmPerson1 = alarmPersonMapper.selectOne(queryWrapper);
                                    }
                                    if (flag) {
                                        AlarmPerson alarmPerson = new AlarmPerson();

                                        QueryWrapper<EmployeeTrack> queryWrapper = new QueryWrapper<>();
                                        queryWrapper.lambda().eq(EmployeeTrack::getEmployeeId, tlEmployee.getId());
                                        queryWrapper.lambda().lt(EmployeeTrack::getTimestamp,alarmEndTime);
                                        queryWrapper.lambda().orderByDesc(EmployeeTrack::getTimestamp);
                                        queryWrapper.lambda().last(" LIMIT 1");
                                        EmployeeTrack employeeTrack = employeeTrackMapper.selectOne(queryWrapper);

                                        if (Objects.nonNull(employeeTrack)) {
                                            alarmPerson.setLat(employeeTrack.getLat());
                                            alarmPerson.setLng(employeeTrack.getLng());
                                            /** 保存地址 **/
                                            String currentAddress = locationUtil.getAddress(employeeTrack.getLng(), employeeTrack.getLat());
                                            if (StringUtils.isNotEmpty(currentAddress)) {
                                                alarmPerson.setAddress(currentAddress);
                                            } else {
                                                alarmPerson.setAddress("");
                                            }

                                            alarmPerson.setAlarmTime(alarmTime);
                                            alarmPerson.setAlarmTypeId(thresholdid);
                                            alarmPerson.setAlarmTypeName(sysname);
                                            alarmPerson.setCreateTime(alarmTime);
                                            alarmPerson.setDepId(tlEmployee.getEmpldeptid());
                                            SysDepart sysDepart = departMap.get(tlEmployee.getEmpldeptid());
                                            if (Objects.nonNull(sysDepart)) {
                                                alarmPerson.setDepName(sysDepart.getDepartName());
                                            }

                                            alarmPerson.setPersonId(tlEmployee.getId());
                                            alarmPerson.setPersonName(tlEmployee.getName());
                                            alarmPerson.setPersonTypeId(tlEmployee.getWorktype());
                                            alarmPerson.setPersonTypeName(tlEmployee.getWorktypename());
                                            alarmPerson.setAlarmStartTime(alarmStartTime);
                                            alarmPerson.setAlarmEndTime(alarmEndTime);

                                            int duration = StringUtils.calLastedTime(alarmStartTime, alarmEndTime);
                                            String time = StringUtils.s2date(Long.parseLong(String.valueOf(duration)));
                                            alarmPerson.setContent("人员离线超过" + time);

                                            alarmPersonMapper.insert(alarmPerson);

                                            //保存更新后的数据
                                            RedisUtil.set(CarPersonTypeNameLastOneKeyToday.token, tlEmployee.getId() + "_" + "离线" + "_" + today, alarmPerson);

                                            flag = false;
                                        }
                                    } else {
                                        int duration = StringUtils.calLastedTime(alarmPerson1.getAlarmStartTime(), alarmEndTime);
                                        String time = StringUtils.s2date(Long.parseLong(String.valueOf(duration)));

                                        alarmPerson1.setIsKeep(1);
                                        alarmPerson1.setAlarmEndTime(alarmEndTime);
                                        alarmPerson1.setContent("人员离线超过" + time);
                                        int a = alarmPersonMapper.updateById(alarmPerson1);

                                        if (a > 0){
                                            //保存更新后的数据
                                            RedisUtil.set(CarPersonTypeNameLastOneKeyToday.token, tlEmployee.getId() + "_" + "离线" + "_" + today, alarmPerson1);
                                        }
                                    }
                                } else {
                                    flag = true;
                                }
                            }
                        }
                    } else {
                        AlarmPerson alarmPerson = new AlarmPerson();

                        QueryWrapper<EmployeeTrack> queryWrapper = new QueryWrapper<>();
                        queryWrapper.lambda().eq(EmployeeTrack::getEmployeeId, tlEmployee.getId());
                        queryWrapper.lambda().lt(EmployeeTrack::getTimestamp,alarmEndTime);
                        queryWrapper.lambda().orderByDesc(EmployeeTrack::getTimestamp);
                        queryWrapper.lambda().last(" LIMIT 1");
                        EmployeeTrack employeeTrack = employeeTrackMapper.selectOne(queryWrapper);

                        if (Objects.nonNull(employeeTrack)) {
                            alarmPerson.setLat(employeeTrack.getLat());
                            alarmPerson.setLng(employeeTrack.getLng());
                            /** 保存地址 **/
                            String currentAddress = locationUtil.getAddress(employeeTrack.getLng(), employeeTrack.getLat());
                            if (StringUtils.isNotEmpty(currentAddress)) {
                                alarmPerson.setAddress(currentAddress);
                            } else {
                                alarmPerson.setAddress("");
                            }

                            alarmPerson.setAlarmTime(alarmTime);
                            alarmPerson.setAlarmTypeId(thresholdid);
                            alarmPerson.setAlarmTypeName(sysname);
                            alarmPerson.setCreateTime(alarmTime);
                            alarmPerson.setDepId(tlEmployee.getEmpldeptid());
                            SysDepart sysDepart = departMap.get(tlEmployee.getEmpldeptid());
                            if (Objects.nonNull(sysDepart)) {
                                alarmPerson.setDepName(sysDepart.getDepartName());
                            }

                            alarmPerson.setPersonId(tlEmployee.getId());
                            alarmPerson.setPersonName(tlEmployee.getName());
                            alarmPerson.setPersonTypeId(tlEmployee.getWorktype());
                            alarmPerson.setPersonTypeName(tlEmployee.getWorktypename());
                            alarmPerson.setAlarmStartTime(alarmStartTime);
                            alarmPerson.setAlarmEndTime(alarmEndTime);

                            int duration = StringUtils.calLastedTime(alarmStartTime, alarmEndTime);
                            String time = StringUtils.s2date(Long.parseLong(String.valueOf(duration)));
                            alarmPerson.setContent("人员离线超过" + time);

                            alarmPersonMapper.insert(alarmPerson);

                            //保存更新后的数据
                            RedisUtil.set(CarPersonTypeNameLastOneKeyToday.token, tlEmployee.getId() + "_" + "离线" + "_" + today, alarmPerson);
                        }
                    }
                }
            }
        }

        //查询所有绑设备的车辆
        QueryWrapper<TlCar> tlCarQueryWrapper = new QueryWrapper<>();
        tlCarQueryWrapper.lambda().eq(TlCar::getStatus, "1");//正常
        List<TlCar> tlCarList = tlCarMapper.selectList(tlCarQueryWrapper);

        //查询所有车辆记录
        QueryWrapper<CarTrack> carTrackQueryWrapper = new QueryWrapper<>();
        carTrackQueryWrapper.lambda().ge(CarTrack::getTimestamp,startTime);
        carTrackQueryWrapper.lambda().le(CarTrack::getTimestamp,endTime);
        List<CarTrack> carTracks = carTrackMapper.selectList(carTrackQueryWrapper);

        Map<String, List<CarTrack>> carTrackMap = carTracks.stream().collect(Collectors.groupingBy(CarTrack::getCarId));

        for (TlCar tlCar : tlCarList) {
            if (Objects.nonNull(tlCar)) {
                TlEquip tlEquip = tlEquipMap.get(tlCar.getId());
                if (Objects.nonNull(tlEquip)) {
                    String eqpnum = String.valueOf(tlEquip.getEquipcode());
                    String carId = "";
                    int calctime = 0;
                    Map thvalue = alarmUtils.getCompare(eqpnum, "离线");
                    if (thvalue != null && thvalue.size() > 0) {
                        int cmpvalue = Integer.parseInt(String.valueOf(thvalue.get("lx"))) * 60;
                        String objid = String.valueOf(thvalue.get("objid"));
                        String thresholdid = String.valueOf(thvalue.get("thresholdid"));
                        String sysname = String.valueOf(thvalue.get("sysname"));

                        JSONObject param = new JSONObject();
                        param.put("id", objid);

                        carId = tlCar.getId();

                        List<CarTrack> carTrackList = carTrackMap.get(carId);

                        Date alarmStartTime = DateUtil.parseDateTime(AttributeUtils.timeCompletion(today, 's'));
                        Date alarmTime = new Date(DateUtil.parseDateTime(AttributeUtils.timeCompletion(today, 's')).getTime() + 1000*60*30);
                        Date alarmEndTime = DateUtil.parseDateTime(AttributeUtils.timeCompletion(today, 'e'));

                        if (Objects.nonNull(carTrackList) && carTrackList.size() > 0){
                            //按照设备上传定位时间正序排序
                            Collections.sort(carTrackList, (o1, o2) -> {
                                Date d1 = o1.getTimestamp();
                                Date d2 = o2.getTimestamp();
                                return d1.compareTo(d2);
                            });

                            Boolean flag = true;
                            for (int i = 0; i < carTrackList.size(); i++) {

                                if (i == 0) {
                                    calctime = StringUtils.calLastedTime(alarmStartTime,carTrackList.get(i).getTimestamp());
                                } else {
                                    calctime = StringUtils.calLastedTime(carTrackList.get(i-1).getTimestamp(),carTrackList.get(i).getTimestamp());
                                    alarmStartTime = carTrackList.get(i-1).getTimestamp();
                                    alarmTime = new Date(alarmStartTime.getTime() + 1000*60*30);
                                }
                                alarmEndTime = carTrackList.get(i).getTimestamp();

                                TlThreshold tlThreshold = thresholdMap.get(carId);
                                if (Objects.nonNull(thresholdid) && StringUtils.isNotEmpty(tlThreshold.getStatus()) && CommonConstant.THRESHOLD_STATUS_YES.equals(tlThreshold.getStatus())) {
                                    if (calctime >= cmpvalue) {

                                        AlarmCar alarmCar1 = RedisUtil.get(CarAlarmTypeNameLastOneKeyToday.token, carId + "_" + "离线" + "_" + today, AlarmCar.class);

                                        if (Objects.isNull(alarmCar1)) {
                                            QueryWrapper<AlarmCar> queryWrapper = new QueryWrapper<>();
                                            queryWrapper.lambda().eq(AlarmCar::getCarId, carId);
                                            queryWrapper.lambda().eq(AlarmCar::getAlarmTypeName, "离线");
                                            queryWrapper.lambda().between(AlarmCar::getAlarmTime, startTime, endTime);
                                            queryWrapper.lambda().orderByDesc(AlarmCar::getAlarmTime);
                                            queryWrapper.lambda().last(" LIMIT 1");
                                            alarmCar1 = alarmCarMapper.selectOne(queryWrapper);
                                        }
                                        if (flag) {
                                            AlarmCar alarmCar = new AlarmCar();

                                            QueryWrapper<CarTrack> queryWrapper = new QueryWrapper<>();
                                            queryWrapper.lambda().eq(CarTrack::getCarId, tlCar.getId());
                                            queryWrapper.lambda().lt(CarTrack::getTimestamp,alarmEndTime);
                                            queryWrapper.lambda().orderByDesc(CarTrack::getTimestamp);
                                            queryWrapper.lambda().last(" LIMIT 1");
                                            CarTrack carTrack = carTrackMapper.selectOne(queryWrapper);

                                            if (Objects.nonNull(carTrack)) {
                                                alarmCar.setLat(carTrack.getLat());
                                                alarmCar.setLng(carTrack.getLng());
                                                /** 保存地址 **/
                                                String currentAddress = locationUtil.getAddress(carTrack.getLng(), carTrack.getLat());
                                                if (StringUtils.isNotEmpty(currentAddress)) {
                                                    alarmCar.setAddress(currentAddress);
                                                } else {
                                                    alarmCar.setAddress("");
                                                }

                                                alarmCar.setCarId(carId);
                                                alarmCar.setCarName(tlCar.getCarnumber());
                                                alarmCar.setDepId(tlCar.getCardeptid());
                                                SysDepart sysDepart = departMap.get(tlCar.getCardeptid());
                                                if (Objects.nonNull(sysDepart)) {
                                                    alarmCar.setDepName(sysDepart.getDepartName());
                                                }

                                                alarmCar.setCreateTime(alarmTime);
                                                alarmCar.setAlarmTime(alarmTime);
                                                alarmCar.setAlarmTypeId(thresholdid);
                                                alarmCar.setAlarmTypeName(sysname);

                                                //根据carId查询type
                                                TlCar tlCar2 = tlCarMapper.selectById(alarmCar.getCarId());
                                                String typeId = "";
                                                String typeName = "";
                                                if (Objects.nonNull(tlCar2) && StringUtils.isNotEmpty(tlCar2.getCartypeid())) {
                                                    typeId = tlCar2.getCartypeid();
                                                    TlCarType tlCarType = tlCarTypeService.getFromRedis(tlCar2.getCartypeid());
                                                    if (Objects.nonNull(tlCarType) && StringUtils.isNotEmpty(tlCarType.getTypename())) {
                                                        typeName = tlCarType.getTypename();
                                                    }
                                                }
                                                alarmCar.setCarTypeId(typeId);
                                                alarmCar.setCarTypeName(typeName);
                                                alarmCar.setAlarmStartTime(alarmStartTime);
                                                alarmCar.setAlarmEndTime(alarmEndTime);

                                                int duration = StringUtils.calLastedTime(alarmStartTime, alarmEndTime);
                                                String time = StringUtils.s2date(Long.parseLong(String.valueOf(duration)));
                                                alarmCar.setContent("设备离线超过" + time);
                                                alarmCar.setAlarmValue(new BigDecimal(duration));
                                                alarmCarMapper.insert(alarmCar);

                                                //保存更新后的数据
                                                RedisUtil.set(CarAlarmTypeNameLastOneKeyToday.token, carId + "_" + "离线" + "_" + today, alarmCar);

                                                flag = false;
                                            }
                                        } else {

                                            int duration = StringUtils.calLastedTime(alarmStartTime, alarmEndTime);
                                            String time = StringUtils.s2date(Long.parseLong(String.valueOf(duration)));

                                            //离线持续保持时间
                                            alarmCar1.setContent("设备离线超过" + time);
                                            alarmCar1.setIsKeep(1);
                                            alarmCar1.setAlarmEndTime(carTrackList.get(i).getTimestamp());
                                            int a = alarmCarMapper.updateById(alarmCar1);
                                            if (a > 0) {
                                                //保存更新后的数据
                                                RedisUtil.set(CarAlarmTypeNameLastOneKeyToday.token, carId + "_" + "离线" + "_" + today, alarmCar1);
                                            }
                                        }
                                    } else {
                                        flag = true;
                                    }
                                }
                            }
                        } else {
                            AlarmCar alarmCar = new AlarmCar();

                            QueryWrapper<CarTrack> queryWrapper = new QueryWrapper<>();
                            queryWrapper.lambda().eq(CarTrack::getCarId, tlCar.getId());
                            queryWrapper.lambda().lt(CarTrack::getTimestamp,alarmEndTime);
                            queryWrapper.lambda().orderByDesc(CarTrack::getTimestamp);
                            queryWrapper.lambda().last(" LIMIT 1");
                            CarTrack carTrack = carTrackMapper.selectOne(queryWrapper);

                            if (Objects.nonNull(carTrack)) {
                                alarmCar.setLat(carTrack.getLat());
                                alarmCar.setLng(carTrack.getLng());
                                /** 保存地址 **/
                                String currentAddress = locationUtil.getAddress(carTrack.getLng(), carTrack.getLat());
                                if (StringUtils.isNotEmpty(currentAddress)) {
                                    alarmCar.setAddress(currentAddress);
                                } else {
                                    alarmCar.setAddress("");
                                }

                                alarmCar.setCarId(carId);
                                alarmCar.setCarName(tlCar.getCarnumber());
                                alarmCar.setDepId(tlCar.getCardeptid());
                                SysDepart sysDepart = departMap.get(tlCar.getCardeptid());
                                if (Objects.nonNull(sysDepart)) {
                                    alarmCar.setDepName(sysDepart.getDepartName());
                                }

                                alarmCar.setCreateTime(alarmTime);
                                alarmCar.setAlarmTime(alarmTime);
                                alarmCar.setAlarmTypeId(thresholdid);
                                alarmCar.setAlarmTypeName(sysname);

                                //根据carId查询type
                                TlCar tlCar2 = tlCarMapper.selectById(alarmCar.getCarId());
                                String typeId = "";
                                String typeName = "";
                                if (Objects.nonNull(tlCar2) && StringUtils.isNotEmpty(tlCar2.getCartypeid())) {
                                    typeId = tlCar2.getCartypeid();
                                    TlCarType tlCarType = tlCarTypeService.getFromRedis(tlCar2.getCartypeid());
                                    if (Objects.nonNull(tlCarType) && StringUtils.isNotEmpty(tlCarType.getTypename())) {
                                        typeName = tlCarType.getTypename();
                                    }
                                }
                                alarmCar.setCarTypeId(typeId);
                                alarmCar.setCarTypeName(typeName);
                                alarmCar.setAlarmStartTime(alarmStartTime);
                                alarmCar.setAlarmEndTime(alarmEndTime);

                                int duration = StringUtils.calLastedTime(alarmStartTime, alarmEndTime);
                                String time = StringUtils.s2date(Long.parseLong(String.valueOf(duration)));
                                alarmCar.setContent("设备离线超过" + time);
                                alarmCar.setAlarmValue(new BigDecimal(duration));
                                alarmCarMapper.insert(alarmCar);

                                //保存更新后的数据
                                RedisUtil.set(CarAlarmTypeNameLastOneKeyToday.token, carId + "_" + "离线" + "_" + today, alarmCar);
                            }
                        }
                    }
                }
            }
        }
        PerformanceMonitor.end();
    }


    /**
     * 报警统计表明细
     * @param request
     * @return
     */
    @RequestMapping(value = "selectAlarmCarForTableDetail", method = RequestMethod.POST)
    public AjaxResult<Object> selectAlarmCarForTableDetail(HttpServletRequest request) {
        try {
            JSONObject params = JSON.parseObject(Tools.getBody(request));
            AlarmCar alarmCar=new AlarmCar();
            if(params!=null){
                alarmCar=JSONObject.parseObject(params.toJSONString(),AlarmCar.class);
            }
            return AjaxResult.success(alarmCarService.selectAlarmCarForTableDetail(alarmCar));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("报错ERROR", e);
            return AjaxResult.fail("操作失败");
        }
    }

    /**
     * 报警统计导出
     * @param request
     * @return
     */
    @RequestMapping(value = "selectAlarmCarForExcel", method = RequestMethod.POST)
    public com.hskn.hss.core.domain.AjaxResult selectAlarmCarForExcel(HttpServletRequest request) {
        try {


            JSONObject params = JSON.parseObject(Tools.getBody(request));
            AlarmCar alarmCar=new AlarmCar();
            if(params!=null){
                alarmCar=JSONObject.parseObject(params.toJSONString(),AlarmCar.class);
            }
            if(alarmCar.getCarNames() == null || alarmCar.getCarNames().size()>0){
                List<AlarmCarChartsExcelVO> oilDeviceServiceVOList =
                    JSONArray.parseArray(JSONObject.toJSONString(alarmCarService.selectAlarmCarForTable(alarmCar)), AlarmCarChartsExcelVO.class);
            //工具类实例化
            ExcelUtil<AlarmCarChartsExcelVO> util = new ExcelUtil<>(AlarmCarChartsExcelVO.class);
            //导出
            return util.exportExcel(oilDeviceServiceVOList, "报警统计表");
            } else{
                return com.hskn.hss.core.domain.AjaxResult.error("请选择至少一条数据导出");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("报错ERROR", e);
            return com.hskn.hss.core.domain.AjaxResult.error();
        }
    }

    /**
     * 报警统计表明细导出
     * @param request
     * @return
     */
    @RequestMapping(value = "selectAlarmCarForExcelDetail", method = RequestMethod.POST)
    public com.hskn.hss.core.domain.AjaxResult selectAlarmCarForExcelDetail(HttpServletRequest request) {
        try {
            JSONObject params = JSON.parseObject(Tools.getBody(request));
            AlarmCar alarmCar=new AlarmCar();
            if(params!=null){
                alarmCar=JSONObject.parseObject(params.toJSONString(),AlarmCar.class);
            }
            if(alarmCar.getAlarmTimes() == null || alarmCar.getAlarmTimes().size()>0){

            List<AlarmCarTableDetailExcelVO> oilDeviceServiceVOList =
                    JSONArray.parseArray(JSONObject.toJSONString(alarmCarService.selectAlarmCarForExcelDetail(alarmCar)), AlarmCarTableDetailExcelVO.class);
            //工具类实例化
            ExcelUtil<AlarmCarTableDetailExcelVO> util = new ExcelUtil<>(AlarmCarTableDetailExcelVO.class);
            //导出
            return util.exportExcel(oilDeviceServiceVOList, "报警统计表明细");
            }else{
                return com.hskn.hss.core.domain.AjaxResult.error("请选择至少一条数据导出");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("报错ERROR", e);
            return com.hskn.hss.core.domain.AjaxResult.error();
        }
    }

}

